#ifndef LRU_HASH_CACHE_HPP
#define LRU_HASH_CACHE_HPP

#include <vector>
#include <thread>
#include <cmath>

#include "./LruCache.hpp"

namespace CachePool
{
    // lru优化：对lru进行分片，提高高并发使用的性能
    template <typename Key, typename Value>
    class LruHashCache
    {
    public:
        LruHashCache(const size_t capacity, const size_t sliceNum)
            : capacity_(capacity), sliceNum_(sliceNum > 0 ? sliceNum : std::thread::hardware_concurrency())
        {
            size_t sliceSize = std::ceil(this->capacity_ / static_cast<double>(this->sliceNum_)); // 获取每个分片的大小，分片要多冗余所以上取整
            for (int i = 0; i < this->sliceNum_; ++i)
            {
                this->lruSliceCaches_.emplace_back(std::make_unique<LruCache<Key, Value>>(sliceSize));
            }
        }

        void set(const Key &key, const Value &value)
        {
            // 获取key的hash值，并计算出对应的分片索引
            size_t sliceIndex = this->calcHash(key) % this->sliceNum_;
            return this->lruSliceCaches_[sliceIndex]->set(key, value);
        }

        bool get(const Key &key, Value &value)
        {
            // 获取key的hash值，并计算出对应的分片索引
            size_t sliceIndex = this->calcHash(key) % this->sliceNum_;
            return this->lruSliceCaches_[sliceIndex]->get(key, value);
        }

        Value get(const Key &key)
        {
            Value value{};
            // memset(&value, 0, sizeof(value));
            this->get(key, value);
            return value;
        }

    private:
        // 将key转换为对应hash值
        size_t calcHash(const Key &key)
        {
            std::hash<Key> hashFunc{};
            return hashFunc(key);
        }

    private:
        size_t capacity_;                                                   // 总容量
        size_t sliceNum_;                                                   // 切片数量
        std::vector<std::unique_ptr<LruCache<Key, Value>>> lruSliceCaches_; // 切片LRU缓存
    };

} // namespace CachePool

#endif // LRU_HASH_CACHE_HPP